﻿using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Office365.SharePointOnline.Cmdlets
{
    [System.Management.Automation.Cmdlet(System.Management.Automation.VerbsLifecycle.Enable, "Feature")]
    public class Enable_Feature : System.Management.Automation.PSCmdlet
    {
        [System.Management.Automation.Parameter(Position = 0, Mandatory = true)]
        public string Url;

        [System.Management.Automation.Parameter(Position = 1, Mandatory = true)]
        public string FeatureId;

        [System.Management.Automation.Parameter(Position = 2, Mandatory = false)]
        public string User;

        [System.Management.Automation.Parameter(Position = 3, Mandatory = false)]
        public string Password;

        // use enum instead?
        [System.Management.Automation.Parameter(Position = 4, Mandatory = false)]
        public string AuthenticationMethod;

        // use only if onpremise authentication
        [System.Management.Automation.Parameter(Position = 5, Mandatory = false)]
        public string Domain;

        [System.Management.Automation.Parameter(Position = 6, Mandatory = true)]
        public bool IsSandboxSolution;

        [System.Management.Automation.Parameter(Position = 6, Mandatory = false)]
        public bool IsSiteScoped;

        // example Enable-Feature -Url https://yoursite.sharepoint.com -FeatureId 44b641e3-d759-465c-855f-c2b43af55a86 -Verbose -User user@yoursite.onmicrosoft.com -Password yourpassword -AuthenticationMethod SharePointOnline
        protected override void ProcessRecord()
        {
            // Initialize
            
            ClientContext context = new ClientContext(Url);
            ICredentials credentials;
            Web web = context.Web;

            // check parameters
            if (string.IsNullOrEmpty(Url))
            {
                this.WriteObject("Error: url is not set");
            }
            else
            {
                if (!string.IsNullOrEmpty(Password) && !string.IsNullOrEmpty(User))
                {
                    AuthenticationHelper authenticationHelper = new AuthenticationHelper() { AuthenticationMethod = AuthenticationMethod, Domain = Domain, Password = Password, User = User };
                    credentials = authenticationHelper.GetCredentials();
                    if (credentials != null)
                    {
                        context.Credentials = credentials as ICredentials;
                    }
                    else
                    {
                        throw new NullReferenceException("No credentials returned.");
                    }
                }
                else
                {
                    this.WriteVerbose("Reusing existing credentials");
                }
                UpdateFeature(context, web);
            }
        }

        private void UpdateFeature(ClientContext context, Web web)
        {
            this.WriteVerbose("Getting features.");
            var features = web.Features;
            // bugfix - this only allowed web scoped features to be activated - so switchting the scope to site
            if (IsSiteScoped)
            {
                this.WriteVerbose(string.Format("Updating sitecollection {0} with site scoped feature {1}", Url, FeatureId));
                features = context.Site.Features;
            }
            else
            {
                this.WriteVerbose(string.Format("Updating web {0} with web scoped feature {1}", Url, FeatureId));
            }
            context.Load(features);
            context.ExecuteQuery();
            
            Guid guid = new Guid(FeatureId);
            // Somehow the featuredefinitionscope must always be set to site even if its web scoped....
            // Actually the enumeration is confusing, set it to farm if the solution is fulltrust and set it to site if it is a sandbox solution
            // see: http://geeks.ms/blogs/lmanez/archive/2013/09/29/office-365-enable-disable-feature-from-power-shell-using-csom.aspx
            if (IsSandboxSolution == true)
            {
                features.Add(guid, true, FeatureDefinitionScope.Site);
            }
            else
            {
                features.Add(guid, true, FeatureDefinitionScope.Farm);
            }
            context.ExecuteQuery();
            this.WriteObject(string.Format("Activated feature {1} on web {0}.", Url, FeatureId));
        }
    }
}
